﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityGameFramework.Runtime;
using GameFramework.Event;
using UnityEngine.UI;
using TowerDefence_Zombie.Data;
using Sirenix.OdinInspector;
using DG.Tweening;
using System.Linq;
using TMPro;
using GameHelper.Tools;
using UnityEngine.Pool;

namespace TowerDefence_Zombie
{
    public class UILevelMainInfoForm : UGuiFormEx
    {
        public Text waveText;
        public Image waveProgressImg;

        private DataPlayer dataPlayer;
        private DataLevel dataLevel;

        public UILevelRoot uiLevelRoot;

        [SerializeField, Title("金币文字")] private TextMeshProUGUI coinText;
        [SerializeField, Title("合成拖拽区域")] private RectTransform synthesisDragArea;
        [SerializeField, Title("炮塔建造器按钮")] private Button buyTowerBtn;
        [SerializeField, Title("炮塔建造器等级")] private TMP_Text buyTowerLevel;
        [SerializeField, Title("炮塔建造器金币")] private TMP_Text buyTowerCoin;

        [SerializeField, Title("拖拽Item")] private ItemSynthesis dragSynthesisItem;
        [SerializeField, Title("开启炮塔面板按钮")] private Button btnOpenTowerPanel;
        [SerializeField, Title("炮塔面板按钮图片")] private Image towerPanelBtnImg;
        [SerializeField, Title("拉升背景")] private RectTransform bgTransform;
        [SerializeField, Title("炮塔面板背景")] private Transform towerPanelTransform;
        [SerializeField, Title("上升按钮图标")] private Sprite upIcon;
        [SerializeField, Title("下降按钮图标")] private Sprite downIcon;

        [SerializeField, Title("关卡通知")] private GameObject levelNotice;
        [SerializeField, Title("关卡通知文本")] private TextMeshProUGUI levelNoticeText;

        [SerializeField, Title("签到按钮")] private Button signInFromBtn;
        [SerializeField, Title("角色升级界面")] private Button HeroUpgradeBtn;
        [SerializeField, Title("角色升级界面红点")] private GameObject HeroUpgradeRedPoint;

        [SerializeField, Title("任务界面")] private Button TaskBtn;
        [SerializeField, Title("商城宝箱界面")] private Button ShopBtn;

        [SerializeField, Title("双倍攻击技能剩余时间")] private TextMeshProUGUI doubleAtkSkillTimeText;
        [SerializeField, Title("双倍金币技能剩余时间")] private TextMeshProUGUI doubleCoinSkillTimeText;
        [SerializeField, Title("双倍技能按钮")] private Button doubleAtkSkillBtn;
        [SerializeField, Title("双倍金币技能按钮")] private Button doubleCoinSkillBtn;

        private readonly Dictionary<int, ItemTowerGrid> _synthesisGridDict = new();
        private int _currentDragSynthesisGridId = -1;
        private bool isTowerPanelOpen = true;

        [SerializeField, Title("掉落金币Icon")] private GameObject coinIcon;
        [SerializeField, Title("掉落金币Root")] private Transform coinRoot;
        [SerializeField, Title("移动终点")] private Transform moveEndPoint;
        private ObjectPool<GameObject> _coinPool;

        [SerializeField, Title("铲车技能Button")] private Button carSkillBtn;
        [SerializeField, Title("铲车技能剩余时间")] private TextMeshProUGUI carSkillTimeText;
        [SerializeField, Title("铲车技能提示")] private GameObject carSkillTip;

        public void OpenCarSkill()
        {
            if (!GameEntry.Data.GetData<DataPlayer>().GetPlayerData().CarSkillData.isUnlock)
            {
                carSkillBtn.gameObject.SetActive(true);
                carSkillBtn.transform.DOScale(new Vector3(1.2f, 1.2f, 1.2f), 0.3f)
                   .SetLoops(-1).SetEase(Ease.InOutQuad);
                carSkillTip.gameObject.SetActive(true);
                GameEntry.Data.GetData<DataPlayer>().GetPlayerData().CarSkillData.isUnlock = true;
            }
        }

        public void CarSkillOnBtnClick()
        {
            if (GameEntry.Data.GetData<DataPlayer>().GetPlayerData().CarSkillData.RemainUnlockTime <= 0 && GameEntry.Procedure.TryGetCurrentProcedure<ProcedureLevel>(out var levelProcedure))
            {
                levelProcedure.LevelControl.ReleaseCarSkill();
                carSkillBtn.transform.DOKill();
                carSkillTip.gameObject.SetActive(false);
                carSkillBtn.transform.localScale = Vector3.one;
                GameEntry.Data.GetData<DataPlayer>().GetPlayerData().CarSkillData.RemainUnlockTime = 600;
                carSkillTimeText.text = "600s";
            }
        }

        public void RefreshCarSkillTime(object sender, GameEventArgs e)
        {
            UpdateCarSkillTimeEventArgs ne = (UpdateCarSkillTimeEventArgs)e;
            int remainTime = (int)ne.RemainingTime;
            if (remainTime > 0)
            {
                carSkillTimeText.text = remainTime.ToString() + "s";
            }
            else
            {
                carSkillTimeText.text = "";
            }
        }

        private void OpenTowerPanel()
        {
            if (!isTowerPanelOpen)
            {
                bgTransform.DOSizeDelta(new Vector2(1080, 848), 0.5f);
                towerPanelTransform.DOLocalMoveY(0, 0.5f);
                towerPanelBtnImg.sprite = downIcon;
                isTowerPanelOpen = true;
            }
            else
            {
                bgTransform.DOSizeDelta(new Vector2(1080, 328), 0.5f);
                towerPanelTransform.DOLocalMoveY(-530, 0.5f);
                towerPanelBtnImg.sprite = upIcon;
                isTowerPanelOpen = false;
            }
        }

        protected override void OnInit(object userData)
        {
            base.OnInit(userData);
            btnOpenTowerPanel.onClick.AddListener(OpenTowerPanel);
            signInFromBtn.onClick.AddListener(OpenSignInForm);
            HeroUpgradeBtn.onClick.AddListener(OpenShopForm);
            TaskBtn.onClick.AddListener(OpenTaskForm);
            ShopBtn.onClick.AddListener(OpenBoxForm);
            doubleAtkSkillBtn.onClick.AddListener(OpneDouleAtkSkill);
            doubleCoinSkillBtn.onClick.AddListener(OpneDouleCoinSkill);
            carSkillBtn.onClick.AddListener(CarSkillOnBtnClick);

            var towerGrids = GetComponentsInChildren<ItemTowerGrid>(true).ToList();
            for (int i = 0; i < towerGrids.Count; i++)
            {
                towerGrids[i].Init(OnBeginDragSynthesisItem);
                _synthesisGridDict.Add(towerGrids[i].GetGridRealId(), towerGrids[i]);
            }
            buyTowerBtn.onClick.AddListener(BuildTowerClick);

        }

        protected override void OnOpen(object userData)
        {
            base.OnOpen(userData);

            Subscribe(UpdateDoubleAtkSkillTimeEventArgs.EventId, SetTimeText);
            Subscribe(UpdateDoubleGlobTimeEventArgs.EventId, SetDoubleCoinSkillTimeText);
            Subscribe(CreatCoinEventAgrs.EventId, OnCreatCoin);

            Subscribe(LazyWaveStartEventArgs.EventId, OnLevelStartWave);
            Subscribe(WaveInfoUpdateEventArgs.EventId, OnWaveUpdate);
            Subscribe(ChangeTowerGridEventArgs.EventId, OnChangeSynthesisGridData);
            Subscribe(UnlockSynthesisEventArgs.EventId, OnSysthesisGridUnlock);
            Subscribe(ChangeCurrencyEventArgs.EventId, OnChangeCurrencyData);
            Subscribe(UpgradeTowerBuilderEventArgs.EventId, OnBuilderUpgrade);
            Subscribe(UpdateCarSkillTimeEventArgs.EventId, RefreshCarSkillTime);

            InitCoinPool();
            dataPlayer = GameEntry.Data.GetData<DataPlayer>();
            dataLevel = GameEntry.Data.GetData<DataLevel>();

            uiLevelRoot.InitLevelRoot();
            coinText.text = ((HugeNum)dataPlayer.GetCurrency(CurrencyType.Coin)).ToString();

            if (dataPlayer.OfflineEarning > 0)
                OpenOfflineEarnForm();

            var curBuilderLevel = GameEntry.Data.GetData<DataPlayer>().GetBuilderLevel();
            if (GameEntry.Data.GetData<DataTower>().GetTowerBuildData(curBuilderLevel, out var buildData))
                RefreshBuilderInfo(curBuilderLevel, buildData.BuildItemNum[0]);
            RefrshHeroUpgradeRedPoint();

            if (GameEntry.Data.GetData<DataPlayer>().GetPlayerData().CarSkillData.isUnlock)
                carSkillBtn.gameObject.SetActive(true);
        }

        private void SetWaveInfo(int currentWave, int totalWave, float progress)
        {
            waveText.text = string.Format("{0}/{1}", currentWave, totalWave);
            waveProgressImg.fillAmount = progress;
        }

        private void OnLevelStartWave(object sender, GameEventArgs e)
        {
            LazyWaveStartEventArgs ne = (LazyWaveStartEventArgs)e;
            if (ne == null)
                return;

            var curLevel = dataLevel.CurrentLevelIndex;
            var curLevelCtrl = dataLevel.CurrentLevel;

            if (dataLevel.GetLevelData(curLevel, out var curLevelData))
            {
                SetWaveInfo(curLevelCtrl.CurrentWaveIndex, curLevelCtrl.WaveCount, 0);
                ShowLevelNotice(curLevel);
                uiLevelRoot.SetUILevelNextLevel();
            }
        }

        private void OnWaveUpdate(object sender, GameEventArgs e)
        {
            WaveInfoUpdateEventArgs ne = (WaveInfoUpdateEventArgs)e;
            if (ne == null)
                return;

            SetWaveInfo(ne.CurrentWave, ne.TotalWave, ne.CurrentWaveProgress);
        }

        /// <summary>
        /// 监听物品修改事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnChangeCurrencyData(object sender, GameEventArgs e)
        {
            ChangeCurrencyEventArgs ne = (ChangeCurrencyEventArgs)e;
            if (ne == null)
                return;

            if (ne.CurrencyType == CurrencyType.Coin)
            {
                coinText.text = ((HugeNum)ne.CurrencyNum).ToString();
            }

            RefrshHeroUpgradeRedPoint();
        }

        /// <summary>
        /// 建造器升级
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnBuilderUpgrade(object sender, GameEventArgs e)
        {
            UpgradeTowerBuilderEventArgs ne = (UpgradeTowerBuilderEventArgs)e;
            if (ne == null)
                return;

            RefreshBuilderInfo(ne.BuilderLevel, ne.BuilderCoin);
        }

        /// <summary>
        /// 刷新建造器信息
        /// </summary>
        /// <param name="level"></param>
        /// <param name="coin"></param>
        private void RefreshBuilderInfo(int level, long coin)
        {
            buyTowerLevel.text = $"Lv {level}";
            buyTowerCoin.text = coin.ToString();
        }

        /// <summary>
        /// 建造炮塔按钮回调
        /// </summary>
        private void BuildTowerClick()
        {
            var dataPlayer = GameEntry.Data.GetData<DataPlayer>();
            var dataSynthesis = GameEntry.Data.GetData<DataSynthesis>();
            if (dataPlayer.CheckCanBuyTower() == false)
            {
                Log.Info($"购买新炮塔失败 - 货币不足");
                return;
            }
            if (dataSynthesis.GetCanUseGrid(out var tarGridId) == false)
            {
                Log.Info($"购买新炮塔失败 - 没有可用的装备栏");
                return;
            }

            if (dataPlayer.BuyTower(out var towerId, out var towerLevel))
            {
                dataSynthesis.ChangeSynthesisGridTower(tarGridId, towerId, towerLevel);
                GameEntry.Sound.PlaySound(EnumSound.BuildTowerMusic, null);
                Log.Info($"获取船新炮塔");
            }
            else Log.Info($"炮塔建造失败");
        }

        #region 合成拖拽相关

        public void RefreshPreviewUI(int towerId, int towerLevel)
        {
            dragSynthesisItem.RefreshTowerInfo(towerId, towerLevel);
        }

        private void OnBeginDragSynthesisItem(int gridId, ItemTowerGrid itemGrid)
        {
            if (GameEntry.Data.GetData<DataSynthesis>().GetSynthesisGridData(gridId, out var gridData)
                && GameEntry.Procedure.TryGetCurrentProcedure<ProcedureLevel>(out var levelProcedure))
            {
                var itemTowerData = GameEntry.Data.GetData<DataTower>().GetTowerData(gridData.TowerId);
                if (levelProcedure.LevelControl.TryProcTowerBeginDrag(itemTowerData, gridData.TowerLevel, TowerInputType.UI, gridId, 0))
                {
                    _currentDragSynthesisGridId = gridId;
                    RefreshPreviewUI(gridData.TowerId, gridData.TowerLevel);
                    itemGrid.SetActivityState(false);
                }
            }
        }

        public bool DragSynthesisItemUI(Vector3 dragPosition, bool isDisableSceneOpera)
        {
            if (CheckDragIsOverlyUI(dragPosition) || isDisableSceneOpera)
            {
                dragSynthesisItem.transform.position = dragPosition;
                dragSynthesisItem.SetActivityState(true);
                return true;
            }
            else
            {
                dragSynthesisItem.SetActivityState(false);
                return false;
            }
        }

        public void StopDragSynthesisItemUI(bool isSuccess)
        {
            dragSynthesisItem.SetActivityState(false);
            if (isSuccess == false
                && _synthesisGridDict.TryGetValue(_currentDragSynthesisGridId, out var itemGrid))
            {
                itemGrid.SetActivityState(true);
            }
            _currentDragSynthesisGridId = -1;
        }

        public bool CheckDragIsOverlyUI(Vector2 pos)
        {
            if (isTowerPanelOpen == false) return false;

            RectTransformUtility.ScreenPointToLocalPointInRectangle(
                synthesisDragArea,
                pos,
                null,
                out var localPoint);

            return synthesisDragArea.rect.Contains(localPoint);
        }

        private void OnChangeSynthesisGridData(object sender, GameEventArgs e)
        {
            ChangeTowerGridEventArgs ne = (ChangeTowerGridEventArgs)e;
            if (ne == null)
                return;

            if (_synthesisGridDict.TryGetValue(ne.GridId, out var gridItem))
            {
                gridItem.RefreshTowerInfo(ne.TowerId, ne.TowerLevel, ne.isUpgrade);
            }
        }

        private void OnSysthesisGridUnlock(object sender, GameEventArgs e)
        {
            UnlockSynthesisEventArgs ne = (UnlockSynthesisEventArgs)e;
            if (ne == null)
                return;

            if (_synthesisGridDict.TryGetValue(ne.GridId, out var gridItem))
            {
                gridItem.RefreshUnLockState(true,true);
            }
        }

        #endregion

        private void ShowLevelNotice(int CurrentLevel)
        {
            levelNotice.GetComponent<CanvasGroup>().alpha = 1;
            levelNoticeText.text = string.Format(LanguageManager.GetLocalizedString("game_level_des"), CurrentLevel);
            levelNotice.SetActive(false);
            levelNotice.SetActive(true);
        }

        private void SetTimeText(object sender, GameEventArgs e)
        {
            UpdateDoubleAtkSkillTimeEventArgs ne = (UpdateDoubleAtkSkillTimeEventArgs)e;
            doubleAtkSkillTimeText.text = ne.RemainingTimeStr;
        }

        private void SetDoubleCoinSkillTimeText(object sender, GameEventArgs e)
        {
            UpdateDoubleGlobTimeEventArgs ne = (UpdateDoubleGlobTimeEventArgs)e;
            doubleCoinSkillTimeText.text = ne.RemainingTimeStr;
        }

        public void InitCoinPool()
        {
            // 创建对象的函数
            System.Func<GameObject> createFunc = () =>
            {
                GameObject coin = Instantiate(coinIcon, coinRoot);
                coin.SetActive(false);
                return coin;
            };

            System.Action<GameObject> actionOnGet = (coin) =>
            {
                coin.SetActive(true);
                coin.transform.localPosition = Vector3.zero;
                coin.transform.rotation = Quaternion.identity;
            };

            System.Action<GameObject> actionOnRelease = (coin) =>
            {
                coin.SetActive(false);
            };

            System.Action<GameObject> actionOnDestroy = (coin) =>
            {
                Destroy(coin);
            };

            _coinPool = new ObjectPool<GameObject>(
                createFunc,
                actionOnGet,
                actionOnRelease,
                actionOnDestroy,
                collectionCheck: true, // 调试时启用，检查重复释放等问题
                10,
                20
            );
        }

        private void OnCreatCoin(object sender, GameEventArgs e)
        {
            CreatCoinEventAgrs ne = (CreatCoinEventAgrs)e;
            if (ne == null)
                return;
            GameObject coin = _coinPool.Get();
            Camera camera = Camera.main;
            Vector3 screenPoint = camera.WorldToScreenPoint(ne.Position);
            coin.transform.position = screenPoint;
            coin.transform.DOMove(moveEndPoint.position, 1f).OnComplete(() =>
            {
                GameEntry.Data.GetData<DataPlayer>().AddCurrency(101, ne.CoinNum, CurrencyEvent.ZombieDrop);
                _coinPool.Release(coin);
            });
        }


        private void RefrshHeroUpgradeRedPoint()
        {
            var hoerUpgradeData = GameEntry.Data.GetData<HeroUpgradeData>();
            if (hoerUpgradeData.TryGetBuilderIsCanUpgrade() ||
               hoerUpgradeData.TryGetTowerPositionIsCanUpgrade() ||
               hoerUpgradeData.TryGetPistolIsCanUpgrade() ||
               hoerUpgradeData.TryGetIceTowerIsCanUpgrade() ||
               hoerUpgradeData.TryGetOldManIsCanUpgrade() ||
               hoerUpgradeData.TryGetIronManIsCanUpgrade())
                HeroUpgradeRedPoint.SetActive(true);
            else
                HeroUpgradeRedPoint.SetActive(false);
        }


        private void OpenSignInForm()
        {
            GameEntry.UI.OpenUIForm(EnumUIForm.UISigninForm);
        }

        private void OpenShopForm()
        {
            GameEntry.UI.OpenUIForm(EnumUIForm.UIHeroUpgradeForm);
        }

        private void OpenBoxForm()
        {
            GameEntry.UI.OpenUIForm(EnumUIForm.UIBoxShoopingFrom);
        }

        private void OpenTaskForm()
        {
            GameEntry.UI.OpenUIForm(EnumUIForm.UITaskFrom);
        }

        private void OpneDouleAtkSkill()
        {
            GameEntry.UI.OpenUIForm(EnumUIForm.UIDoubleAttackForm);
        }

        private void OpneDouleCoinSkill()
        {
            GameEntry.UI.OpenUIForm(EnumUIForm.UIDoubleGolb);
        }

        private void OpenOfflineEarnForm()
        {
            GameEntry.UI.OpenUIForm(EnumUIForm.UIOfflineEarningsForm);
        }
    }
}

